/**
 * Copyright (C) 2010 - 2013 Harry Glasgow
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.googlecode.jaden.common.config;

import com.googlecode.jaden.common.enums.IOType;
import com.googlecode.jaden.common.enums.DateResultType;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

public class IOConfiguration implements Serializable {

    private static final long serialVersionUID = 100;

    private IOType type = IOType.Numeric;

    private final boolean outputConfig;

    // Name
    private String name = "";

    // Numeric
    private int numericMinValue = -1;
    private int numericMaxValue = 1;

    // Map
    private final Map<String, Double> map = new TreeMap<String, Double>();

    // Categorical
    private final List<String> categoricalList = new ArrayList<String>();
    // - For categorical input type
    private boolean categoricalCyclic;

    // Date
    private String dateFormat = "MM/dd/yyyy HH:mm:ss";
    private DateResultType dateResultType = DateResultType.DayOfYear;

    public IOConfiguration(boolean outputConfig) {
        this.outputConfig = outputConfig;
    }

    public IOConfiguration copy() {
        IOConfiguration copy = new IOConfiguration(outputConfig);
        copy.numericMinValue = numericMinValue;
        copy.numericMaxValue = numericMaxValue;
        copy.categoricalCyclic = categoricalCyclic;
        copy.type = type;
        copy.map.putAll(map);
        copy.categoricalList.addAll(categoricalList);
        copy.name = name;
        copy.dateFormat = dateFormat;
        copy.dateResultType = dateResultType;
        return copy;
    }

    public boolean isOutputConfig() {
        return outputConfig;
    }

    public boolean isCategoricalCyclic() {
        return categoricalCyclic;
    }

    public void setCategoricalCyclic(boolean categoricalCyclic) {
        this.categoricalCyclic = categoricalCyclic;
    }

    public int getNumericMaxValue() {
        return numericMaxValue;
    }

    public void setNumericMaxValue(int numericMaxValue) {
        this.numericMaxValue = numericMaxValue;
    }

    public int getNumericMinValue() {
        return numericMinValue;
    }

    public void setNumericMinValue(int numericMinValue) {
        this.numericMinValue = numericMinValue;
    }

    public IOType getType() {
        return type;
    }

    public void setType(IOType type) {
        this.type = type;
    }

    public List<String> getCategoricalList() {
        return categoricalList;
    }

    public Map<String, Double> getMap() {
        return map;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDateFormat() {
        return dateFormat;
    }

    public void setDateFormat(String dateFormat) {
        this.dateFormat = dateFormat;
    }

    public DateResultType getDateResultType() {
        return dateResultType;
    }

    public void setDateResultType(DateResultType dateResultType) {
        this.dateResultType = dateResultType;
    }

    public int getInternalWidth() {
        if (type == IOType.Numeric) {
            return 1;
        } else if (type == IOType.Categorical) {
             return categoricalCyclic ? 2 : categoricalList.size();
        } else if (type == IOType.Map) {
            return 1;
        } else if (type == IOType.Date) {
            if (dateResultType == DateResultType.MonthCategorical) {
                return 12;
            } else if (dateResultType == DateResultType.DayOfWeekCategorical) {
                return 7;
            }
            return 2;
        } else {
            throw new IllegalStateException("Type ? " + type);
        }
    }

    /**
     * Get rid of any extraneous data.
     */
    public void compress() {
        if (type != IOType.Categorical) {
            categoricalList.clear();
        }

        if (type != IOType.Map) {
            map.clear();
        }
    }
}
